#include "PSFEventAction.hh"

#include "PSFEventActionMessenger.hh"
#include "PSFPhotonDetHit.hh"
#include "PSFRun.hh"
#include "PSFRunAction.hh"

#include "G4AnalysisManager.hh"
#include "G4Event.hh"
#include "G4EventManager.hh"
#include "G4RunManager.hh"
#include "G4SDManager.hh"
#include "G4TrajectoryContainer.hh"
#include "G4VVisManager.hh"
#include "G4HCofThisEvent.hh"
#include "G4UnitsTable.hh"
#include "Randomize.hh"
#include <iomanip>

// Purpose: Accumulates statistics regarding hits
//          in the PhotonDet detector

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

PSFEventAction::PSFEventAction()
{
  fEventMessenger = new PSFEventActionMessenger(this);
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

PSFEventAction::~PSFEventAction() { delete fEventMessenger; }

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void PSFEventAction::BeginOfEventAction(const G4Event *)
{

  fNTIR = 0;
  fNExiting = 0;
  fEscapedEnd = 0;
  fEscapedMid = 0;
  fBounce = 0;
  fPSFCoreBounce = 0;
  fClad1Bounce = 0;
  fClad2Bounce = 0;
  fReflected = 0;
  fEscaped = 0;
  fMirror = 0;
  /////////////////////////////////
  fPEdep = 0.;
  fPNPhoton = 0;
  fFiberZ = 0.;

  fCoreTIR = 0;
  fCoreR = 0;
  fClad1TIR = 0;
  fClad1R = 0;
  fCoupleR = 0.;

  fAbsCoreL = 0.;
  fAbsClad1L = 0.;

  fInitGamma = -1;
  fInitCoupleR = -1.;
  fInitDet = -1.;
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void PSFEventAction::EndOfEventAction(const G4Event *evt)
{

  // Get Hits from the detector if any
  G4SDManager *SDman = G4SDManager::GetSDMpointer();
  G4String colName = "PhotonDetHitCollection";
  fMPPCCollID = SDman->GetCollectionID(colName);

  G4HCofThisEvent *HCE = evt->GetHCofThisEvent();
  PSFPhotonDetHitsCollection *mppcHC = nullptr;

  // Get the hit collections
  if (HCE)
  {
    if (fMPPCCollID >= 0)
    {
      mppcHC = (PSFPhotonDetHitsCollection *)(HCE->GetHC(fMPPCCollID));
    }
  }

  // Get hit information about photons that reached the detector in this event
  G4int n_hit = 0;
  if (mppcHC)
  {
    n_hit = mppcHC->entries();
  }

  auto analysisManager = G4AnalysisManager::Instance();
  // 填充每一个Hit的信息
  // 清除元组
  fVecEnergy.clear();
  fVecTime.clear();
  fVecDetectorIndex.clear();
  fVecPosX.clear();
  fVecPosY.clear();
  fVecPosZ.clear();
  fVecDirX.clear();
  fVecDirY.clear();
  fVecDirZ.clear();
  fVecDirTheta.clear();
  fVecDirPhi.clear();
  for (size_t i = 0; i < mppcHC->entries(); ++i)
  {
    auto pdHit = (*mppcHC)[i];
    fVecEnergy.push_back(pdHit->GetEnergy() / CLHEP::eV);                  // 填充探测器探测光子能量
    fVecTime.push_back(pdHit->GetArrivalTime() / CLHEP::ns);               // 填充探测器探测光子时间
    fVecDetectorIndex.push_back(pdHit->GetDetNumber());                    // 填充探测器编号
    fVecPosX.push_back(pdHit->GetArrivalPos().x() / CLHEP::mm);            // 填充探测器探测光子位置
    fVecPosY.push_back(pdHit->GetArrivalPos().y() / CLHEP::mm);            // 填充探测器探测光子位置
    fVecPosZ.push_back(pdHit->GetArrivalPos().z() / CLHEP::mm);            // 填充探测器探测光子位置
    fVecDirX.push_back(pdHit->GetPosDir().x());                            // 填充探测器探测光子角度
    fVecDirY.push_back(pdHit->GetPosDir().y());                            // 填充探测器探测光子角度
    fVecDirZ.push_back(pdHit->GetPosDir().z());                            // 填充探测器探测光子角度
    fVecDirTheta.push_back(pdHit->GetPosDir().theta() * 180. / CLHEP::pi); // 填充探测器探测光子角度
    fVecDirPhi.push_back(pdHit->GetPosDir().phi() * 180. / CLHEP::pi);     // 填充探测器探测光子角度
  }
  // 填充一个Eevent的信息
  // 清除元组
  fVecNPhoton.clear();
  fVecPEdep.clear();
  fVecNPPhoton.clear();
  // 填充元组
  fVecNPhoton.push_back(mppcHC->entries()); // 填充探测器探测光子数
  fVecPEdep.push_back(fPEdep / CLHEP::keV); // 填充缪子沉积能量
  fVecNPPhoton.push_back(fPNPhoton);        // 填充初始光子数

  analysisManager->AddNtupleRow();

  if (fVerboseLevel > 1)
  {
    G4cout << "-------------------------------------" << G4endl
           << " In this event, number of:" << G4endl
           << "  TIR:               " << fNTIR << G4endl
           << "  Exiting:           " << fNExiting << G4endl
           << "  Escaped Mid:       " << fEscapedMid << G4endl
           << "  Escaped End:       " << fEscapedEnd << G4endl
           << "  Bounced:           " << fBounce << G4endl
           << "  PSFCore Bounce:    " << fPSFCoreBounce << G4endl
           << "  Clad1 Bounce:      " << fClad1Bounce << G4endl
           << "  Clad2 Bounce:      " << fClad2Bounce << G4endl
           << "  Reflected:         " << fReflected << G4endl
           << "  Escaped:           " << fEscaped << G4endl
           << "  Mirror:            " << fMirror << G4endl
           << "  CoreTIR:           " << fCoreTIR << G4endl
           << "  CoreR:             " << fCoreR << G4endl
           << "  Clad1TIR:          " << fClad1TIR << G4endl
           << "  Clad1R:            " << fClad1R << G4endl
           << "  CoupleR:           " << fCoupleR << G4endl
           << "  AbsCoreL:          " << fAbsCoreL << G4endl
           << "  AbsClad1L:         " << fAbsClad1L << G4endl
           << "  AbsClad1L+AbsCoreL:" << fAbsClad1L + fAbsCoreL << G4endl
           << "  Detector hit:      " << n_hit << G4endl;
  }
  auto run = static_cast<PSFRun *>(
      G4RunManager::GetRunManager()->GetNonConstCurrentRun());
  if (fVerboseLevel > 0)
  {
    run->AddTIR(fNTIR);
    run->AddExiting(fNExiting);
    run->AddEscapedEnd(fEscapedEnd);
    run->AddEscapedMid(fEscapedMid);
    run->AddBounce(fBounce);
    run->AddPSFCoreBounce(fPSFCoreBounce);
    run->AddClad1Bounce(fClad1Bounce);
    run->AddClad2Bounce(fClad2Bounce);
    run->AddReflected(fReflected);
    run->AddEscaped(fEscaped);
    run->AddMirror(fMirror);
    run->AddDetectorHits(n_hit);
    run->AddCoreTIR(fCoreTIR);
    run->AddCoreR(fCoreR);
    run->AddClad1TIR(fClad1TIR);
    run->AddClad1R(fClad1R);
    run->AddCoupleR(fCoupleR);
  }
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

G4int PSFEventAction::GetEventNo()
{
  return fpEventManager->GetConstCurrentEvent()->GetEventID();
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

void PSFEventAction::SetEventVerbose(G4int level) { fVerboseLevel = level; }
